﻿// (c) Copyright Max Kazarin.
// This source is subject to the Microsoft Permissive License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.

/// <reference path='../Common/jquery-1.3.2.js' />
// <reference path='../Common/MicrosoftAjax.debug.js' />

Type.registerNamespace('jQueryNET.Controls');

jQueryNET.Controls.ContextMenu = function jQueryNET$Controls$ContextMenu(element) {
	/// <summary>
	/// This class implement ContextMenu control
	/// </summary>
	/// <param name='element' type='Sys.UI.DomElement' domElement='true'>
	/// DOM element the control is associated with
	/// </param>

	jQueryNET.Controls.ContextMenu.initializeBase(this, [element]);

	this._rootElement
		.addClass('contextmenu')
	this._rootElement.attr({
		autocomplete: 'off'
	})

	this._innerListElement = this._rootElement
		.append('<ul class="contextmenu_list"></ul>').find('ul.contextmenu_list:last');

	this._onDocumentMouseDownHandler = Function.eventWraper(this, this._onDocumentMouseDown);
	this._onItemMouseOverHandler = Function.eventWraper(this, this._onItemMouseOver);
	this._onItemMouseOutHandler = Function.eventWraper(this, this._onItemMouseOut);
	this._onClickHandler = Function.eventWraper(this, this._onClick);

	this._onSubMenuClickHandler = Function.createDelegate(this, this._onSubMenuClick);
	
	this._subMenuActiveHandler = Function.createDelegate(this, this._subMenuActive);
}

jQueryNET.Controls.ContextMenu.createElement = function(parent) {
	/// <summary>
	/// Static method for using on client-side. Create DOM element the control
	/// associated with
	/// </summary>
	/// <param name='parent' type='Sys.UI.DomElement' domElement='true'>
	/// Parent DOM element or jQuery selector
	/// </param>

	var element =
		$(parent)
			.append('<div>')
			.find('div:last');

	return element.get(0);
}

function jQueryNET$Controls$ContextMenu$initialize() {
	/// <summary>
	/// Initialize the control
	/// </summary>
	jQueryNET.Controls.ContextMenu.callBaseMethod(this, 'initialize');

	$(document)
		.bind('mousedown', this._onDocumentMouseDownHandler)

	this._innerListElement.bind('click', this._onClickHandler);
	this.set_width(0);
}

function jQueryNET$Controls$ContextMenu$dispose() {
	/// <summary>
	/// Dispose the control
	/// </summary>

	$(document)
		.unbind('mousedown', this._onDocumentMouseDownHandler);

	this._innerListElement.unbind('click', this._onClickHandler);

	if (this._subMenu)
		this._subMenu.dispose();

	this._rootElement.remove();
	
	jQueryNET.Controls.ContextMenu.callBaseMethod(this, 'dispose');
}

function jQueryNET$Controls$ContextMenu$get_items() {
	if (arguments.length !== 0) throw Error.parameterCount();
	if (this._items == null)
		this._items = new Array();

	return this._items;
}

function jQueryNET$Controls$ContextMenu$set_items(value) {
	if (!Array.isInstanceOfType(value))
		value = Sys.Serialization.JavaScriptSerializer.deserialize(value);

	var e = Function._validateParams(arguments, [{ name: "value", type: Object, mayBeNull: true}]);
	if (e) throw e;

	var items = this.get_items();
	Array.forEach(
		value,
		function(element, index, array) {
			items.push(element);
			//this.add_item(element)
		},
		this);
}

function jQueryNET$Controls$ContextMenu$get_selectedItem() {
	if (arguments.length !== 0) throw Error.parameterCount();
	return this._selectedItem;
}

function jQueryNET$Controls$ContextMenu$get_selectedValue() {
	if (arguments.length !== 0) throw Error.parameterCount();

	if (this._selectedItem)
		return this._selectedItem.Value;

	return null;
}

function jQueryNET$Controls$ContextMenu$add_item(item, index) {
	var parentItemClass = '';
	if (item.ChildItems != null && item.ChildItems.length > 0)
		parentItemClass = 'contextmenu_item_arrow';

	var html = '<li id="' + index + '" class="contextmenu_list_item';
	if (!item.Enabled)
		html += ' disabled';

	if (item.Text == '-')
		html += ' contextmenu_separator">' +
				'<span></span></li>';
	else
		html += '"><a class="contextmenu_item ' + parentItemClass + '" href="#">' +
				'<img src="<%=WebResource("jQueryNET.Common.Images.s.gif")%>" class="contextmenu_item_icon" style="background-image:url(' + item.ImageUrl + ')">' +
				item.Text +
				'</a></li>';

	this._innerListElement.append(html);
	var itemElement = this._innerListElement.find('li.contextmenu_list_item:last');
	var width = itemElement.width();
	if (this._itemWidth < width)
		this._itemWidth = width; 
	
	//if (this.get_width() < itemElement.width()) {
	//	this.set_width(itemElement.width());
	//}

	itemElement.hover(this._onItemMouseOverHandler, this._onItemMouseOutHandler);
}

function jQueryNET$Controls$ContextMenu$show(x, y) {
	if (this._subMenu) {
		this._subMenu.dispose();
		this._subMenu = null;
	}

	this._innerListElement.empty();
	var items = this.get_items();
	Array.forEach(
		items,
		function(item, index, array) {
			this.add_item(item, index)
		},
		this);

	this._rootElement.find('li.contextmenu_separator span').width(this._itemWidth);
	this.set_height(this.get_items().length * this._innerListElement.find('li.contextmenu_list_item:last').outerHeight());

	this._rootElement.attr(
		'style', 'left: ' + x + 'px;' +
				'top: ' + y + 'px;' +
				'visibility:visible;');
}

function jQueryNET$Controls$ContextMenu$hide() {
	this._rootElement.removeAttr('style');
}

function jQueryNET$Controls$ContextMenu$_showSubMenu(item, itemElement) {
	this._hideSubMenu.stop();
	this._hideSubMenu();

	this._subMenuElement = itemElement;
	
	this._subMenu = $create(
			jQueryNET.Controls.ContextMenu,
			null,
			null,
			null,
			jQueryNET.Controls.ContextMenu.createElement(this._rootElement.parent().get(0)));

	this._subMenu.add_active(this._subMenuActiveHandler);
	this._subMenu.add_itemClick(this._onSubMenuClickHandler);
	this._subMenu.set_items(item.ChildItems);

	var window = $(window);

	var position = itemElement.offset();
	var menuPosition = this._rootElement.offset();
	var left = menuPosition.left + this.get_width() - 3;
	if (left + this._subMenu.get_width() > window.width())
		left -= this._subMenu.get_width() + this.get_width() + 6;

	this._subMenu.show(left, position.top);
}

function jQueryNET$Controls$ContextMenu$_hideSubMenu() {
	if (this._subMenu == null)
		return;

	this._subMenu.dispose();
	this._subMenu = null;
	this._subMenuElement = null;
}

function jQueryNET$Controls$ContextMenu$_subMenuActive() {
	this._hideSubMenu.stop();
	this._showSubMenu.stop();
	this._selectedElement = this._subMenuElement;
	this._subMenuElement.addClass('contextmenu_item_active');
}

function jQueryNET$Controls$ContextMenu$set_selectedElement(element) {
	if (this._subMenu &&
		!this._hideSubMenu.isBusy())
		this._hideSubMenu.wait(this._waitTime, this);

	this._selectedElement = element;
}

function jQueryNET$Controls$ContextMenu$_onDocumentMouseDown(event, sender) {
	if ($(event.target).closest('div.contextmenu').size() == 0)
		this.hide();
}

function jQueryNET$Controls$ContextMenu$_onItemMouseOver(event, sender) {
	var itemElement = $(sender);

	if (this._selectedElement != null &&
		this._selectedElement.get(0) != itemElement.get(0))
		this._selectedElement.removeClass('contextmenu_item_active');

	var item = this.get_items()[itemElement.get(0).id];
	if (!item.Enabled) {
		this.set_selectedElement();
		return;
	}
		
	if (item.Text != '-')
		itemElement.addClass('contextmenu_item_active');

	if (item.ChildItems != null &&
		item.ChildItems.length > 0)
		if (this._subMenu == null ||
			this._subMenuElement.get(0) != itemElement.get(0))
			this._showSubMenu.wait(this._waitTime, this, item, itemElement);
		else
			this._hideSubMenu.stop();
			
	this.set_selectedElement(itemElement)
}

function jQueryNET$Controls$ContextMenu$_onItemMouseOut(event, sender) {
	var itemElement = $(sender);

	var item = this.get_items()[itemElement.get(0).id];

	this._showSubMenu.stop();
	if (this._subMenu &&
		!this._hideSubMenu.isBusy())
		this._hideSubMenu.wait(this._waitTime, this, itemElement);

	itemElement.removeClass('contextmenu_item_active');
}

function jQueryNET$Controls$ContextMenu$_onClick(event, sender) {
	var itemElement = $(event.target).closest('li:contextmenu_list_item');
	var item = this.get_items()[itemElement.get(0).id];

	if (!item.Enabled || 
		(item.ChildItems != null &&	item.ChildItems.length > 0))
		return
		
	this.hide();
	this.raiseItemClick(item);
}

function jQueryNET$Controls$ContextMenu$_onSubMenuClick(sender, item) {
	this.hide();
	this.raiseItemClick(item);
}

function jQueryNET$Data$DataSourceBase$add_itemClick(handler) {
	/// <summary>
	/// Add an event handler for the item click event
	/// </summary>
	/// <param name='handler' type='Function' mayBeNull='false'>
	/// Event handler
	/// </param>
	/// <returns />

	this.get_events().addHandler('itemClick', handler);
}

function jQueryNET$Data$DataSourceBase$remove_itemClick(handler) {
	/// <summary>
	/// Remove an event handler from the item click event
	/// </summary>
	/// <param name='handler' type='Function' mayBeNull='false'>
	/// Event handler
	/// </param>
	/// <returns />

	this.get_events().removeHandler('itemClick', handler);
}

function jQueryNET$Data$DataSourceBase$raiseItemClick(eventArgs) {
	/// <summary>
	/// Raise the item click event
	/// </summary>
	/// <param name='eventArgs' type='Sys.CancelEventArgs' mayBeNull='false'>
	/// Event arguments for the click event
	/// </param>
	/// <returns />

	var handler = this.get_events().getHandler('itemClick');
	if (handler) {
		handler(this, eventArgs);
	}
}

jQueryNET.Controls.ContextMenu.prototype = {
	_selectedItem: null,
	_selectedElement: null,
	_subMenuElement: null,
	_waitTime: 300,
	_itemWidth: 0,

	initialize: jQueryNET$Controls$ContextMenu$initialize,
	dispose: jQueryNET$Controls$ContextMenu$dispose,

	get_items: jQueryNET$Controls$ContextMenu$get_items,
	set_items: jQueryNET$Controls$ContextMenu$set_items,
	get_selectedItem: jQueryNET$Controls$ContextMenu$get_selectedItem,
	get_selectedValue: jQueryNET$Controls$ContextMenu$get_selectedValue,
	set_selectedElement: jQueryNET$Controls$ContextMenu$set_selectedElement,
	
	add_item: jQueryNET$Controls$ContextMenu$add_item,

	show: jQueryNET$Controls$ContextMenu$show,
	hide: jQueryNET$Controls$ContextMenu$hide,
	
	_showSubMenu: jQueryNET$Controls$ContextMenu$_showSubMenu,
	_hideSubMenu: jQueryNET$Controls$ContextMenu$_hideSubMenu,
	_subMenuActive: jQueryNET$Controls$ContextMenu$_subMenuActive,

	_onDocumentMouseDown: jQueryNET$Controls$ContextMenu$_onDocumentMouseDown,
	_onItemMouseOver: jQueryNET$Controls$ContextMenu$_onItemMouseOver,
	_onItemMouseOut: jQueryNET$Controls$ContextMenu$_onItemMouseOut,
	_onClick: jQueryNET$Controls$ContextMenu$_onClick,
	_onSubMenuClick: jQueryNET$Controls$ContextMenu$_onSubMenuClick,
	
	add_itemClick: jQueryNET$Data$DataSourceBase$add_itemClick,
	remove_itemClick: jQueryNET$Data$DataSourceBase$remove_itemClick,
	raiseItemClick: jQueryNET$Data$DataSourceBase$raiseItemClick
}

jQueryNET.Controls.ContextMenu.registerClass('jQueryNET.Controls.ContextMenu', jQueryNET.Controls.ControlBase);